/***************************************************************
                       c2am.c V3
Routines and interface for Main Analysis
**************************************************************/
#include <stdio.h>
#include <malloc.h>
#include <pwd.h>
#include <limits.h>
#include "../seq/tree.h"

#ifndef MAC_BUILD
#include <wait.h>
#else
#include <sys/wait.h>
#endif

#include "clam.h"
#include <gtk/gtkwidget.h>
#include <sys/times.h>

extern int Zbatch_flag;
extern int ZburyFlag;
extern int Znum_merge, Znum_ctg0;
extern char tolText[14], cutText[14], burText[14], 
      uncText[14], endText[14], bestText[14];
extern GtkWidget *ctg_window;
extern void show_help();
extern BOOL ZboolCpM();
extern void CpMdisplay(), AutoCtgMsg(), unbury();
extern void ClamShare();
extern void precompute_sulston();
extern void setmarkerposctg();
extern FILE *graphQueryOpen(); 
extern void pr_end_timer();

void Zbuild_contigs(), Zincremental();
extern void quitCpM(), ZautoCpM(), Zbuild_contigs_zap(), Zincremental_build_zap();
extern int ZscoreCpM(struct tmpCz*, struct tmpCz*, struct tmpSz*), Zcnt_shared_markers(struct tmpCz*, struct tmpCz*, struct tmpSz*);
extern void afterkillall(),  refreshlist(), removespaces();
extern int move_selected(), save_fpc_safe(), after_contigs_changed(); /** fpp **/
extern void updateproj(), Zproj_results(), Zopenlog(); 
extern void Zrule_menu(), quitCB(), set_Zunc();
extern int fppFindClone(), loadCz(), ZibcCpM();
extern void Zcalc_zap(), Zall_unbury(), CBlayout(), displayProj();
extern void matchends();
extern void Zfree_cb_data_structures();
static void nameZfpc(), nameZkeyset(); /* cari 1/30/04 add function */
static void Zkill_all(),  pickg9(), hitCR();

extern FPC_TREE seq_tree;
extern int ends_ends_seq_confirm;

void  keyset2fpc();  
static void DQ_ctgs(); 
static void reanalyze_all_ctgs(); 

int g92;
extern char scoreText[60];

static int endsFlag=0, ctg0Flag=0, ends_seq_Flag = 0;
static int seqArc, noCBArc, aaddArc, endsArc, ctg0Arc, useCpMArc, logArc, stdArc, seq_endsArc;
static int precomputeArc, qSplitArc, qBuild1Arc, qBuild2Arc;
static int  ctgBox, scoreBox, tolBox, cutBox, burFltBox, 
             dateBox, nameBox, endBox, matchBox, bandBox,  bestBox;

static int qCutoffBox; 
float qDQFactor = .1;
static char qDQStepText[5];

static char dateText[30],  ctgText[14], ZnameText[CLONE_SZ+2];
static char matchText[14];
static char qCutoffText[5];  

extern int called_by_merge;

#define Show {if (graphActivate(g92)){graphPop(); graphRedraw();}}
#define Output {if (Pz.logFlag) {fprintf(Zlogfp,"%s",ZBuf); fflush(Zlogfp);} \
      if (!Zbatch_flag && Pz.stdFlag) {printf("%s",ZBuf); fflush(stdout);}}

static void type0() { Zrule_menu(2); }
int Zkill_seq=1; 
int ZnoCB=0;     /* cari 1Mar07 - for IBC, don't run CB algorithm if on */

static void Zhelp0() {
show_help("Parameters", "parameters");
}
static void Zhelp1() {
show_help("Main Analysis/Ends->Ends,KeySet->FPC", "main_comparisons");
}
static void Zhelp2() {
show_help("Main Analysis/Build Contigs", "main_build");
}
static void Zhelp3() {
show_help("Main Analysis/DQer-ReBuild", "main_reanalyze");
}
static void Zhelp4() {
show_help("Main Analysis/Clone", "main_clone_cmp");
}
/**********************************************************
                  DEF: fix_cb_offsets
***********************************************************/
/* put the leftmost cb to 0 on all contigs */
void fix_cb_offsets()
{
    int i, c, tempctg;
    CLONE* clp;

    for(i=1;i<=max_contig;i++)
    {
       if (contigs[i].ctg == 0) continue;
       if (contigs[i].count == 0) continue;
       if (contigs[i].ctgstat == DEAD) continue;
       if (contigs[i].left == 0) continue;

       c= contigs[i].start;
       while (1)
       {
          clp = arrp(acedata, c, CLONE);
          clp->x -= contigs[i].left;
          clp->y -= contigs[i].left;
          if (c == contigs[i].last) break;
          else c= clp->next;
       }
       contigs[i].right -= contigs[i].left;
       contigs[i].left = 0;

       /* WN 7/11/04 markers have to get reset with contig */
       tempctg = currentctg;
       currentctg = i;
       setmarkerposctg();
       currentctg = tempctg;
    }
}
/**************************************************************
                    DEF: clearMsg()
***************************************************************/
void clearMsg()
{
int i;
  for (i=0; i< 4; i++) Proj.msg2[i][0] = '\0';
  for (i=0; i<= max_contig ; i++) contigs[i].projmsg[0] = '\0';
}
/****************************************************************
                    DEF: quitClam2();
*****************************************************************/
void quitClam2()
{
   if (graphActivate(g92)) {
      graphDestroy();
      if (graphActivate(grule)) graphDestroy();
      quitCpM();
   }
}
/************************************************************
                    DEF: showClam()
************************************************************/
void showClam2()
{
   if (graphActivate(g92)) {
      strcpy(scoreText,ZBuf);
      Show;
   }
}
/*********************************************************
                  DEF: ClamCtgDisplay2
*********************************************************/
void ClamCtgDisplay2()
{
float row;
float i=0.0, col1=2.0,  width=50.0;
static MENUOPT amenu[] = { { quitClam2, "Close" },
    { type0, "The Attic"},  
    { graphPrint,"Print Screen"}, 
    { 0, 0 } } ;
char tmp[40], year[5];
int new_year;

  if (!dataloaded) return;
  if (!arrayExists(bands)) 
      if (fpRead() == -1) {
          displaymess("No cor file - no analysis");
          return;
      }
  if(graphActivate(g92)){   
     if (!NoPop) graphPop();
  }
  else if (NoPop) return;
  else{
    g92 = graphCreate (TEXT_FIT,"FPC Main Analysis",.2,.2,.435,.550) ;
    graphRegister (PICK, pickg9) ;
    scoreText[0] = '\0';
    ZnameText[0] = '\0';
    if (Pz.logFlag && Zlogfp==NULL) Zopenlog();
  }
  sprintf(cutText,"%.0e",Pz.cutFlt);
  sprintf(burText,"%2.3f",Pz.burFlt);
  sprintf(endText,"%d",Pz.fromendInt);
  sprintf(matchText,"%d",Pz.mergeMatches);
  sprintf(bestText,"%d",Pz.bestInt);
  if (Pz.killInt == -1) sprintf(ctgText,"max");
  else sprintf(ctgText,"%d",Pz.killInt);

  if (0 == Pz.DQusePct) {
     sprintf(qCutoffText,"%d",Pz.DQnumq);  
  }
  else {
     sprintf(qCutoffText,"%d%%",Pz.DQnumq);  
  }
  sprintf(qDQStepText,"%d",Pz.DQstep);  

  graphClear();
  graphMenu(amenu);
  sprintf(tolText,"%d",Pz.tol);

    row = 1.0;

    graphText("Tolerance:",col1,row);
    tolBox = graphTextEntry(tolText, 4, 13, row,hitCR);

    graphText("Cutoff:",18,row);
    cutBox = graphTextEntry(cutText, 6, 26, row,hitCR);

    graphText("Bury~:",33,row);
    burFltBox = graphTextEntry(burText, 5, 40, row,hitCR);

    row += 2.0;
    i=3.0;
    precomputeArc = graphBoxStart();
      graphArc(i, row+0.5, 0.7, 0, 360);
      if (Pz.precompute) graphFillArc(i, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(precomputeArc, BLACK, TRANSPARENT);
    graphText("Precompute",i+1.0,row);

    i+=14.0;
    useCpMArc = graphBoxStart();
      graphArc(i, row+0.5, 0.7, 0, 360);
      if (Cp.useFlag) graphFillArc(i, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(useCpMArc, BLACK, TRANSPARENT);
    graphText("Use CpM",i+1.0,row);
    i+=10.0;
    graphButton("CpM Table",CpMdisplay,i,row);

    row += 2.0;
    scoreBox = graphBoxStart();
    graphTextPtr(scoreText,1.0,row,45);
    graphBoxEnd();
    graphBoxDraw(scoreBox,BLACK,CYAN);

    row += 2.0;
    i=3.0;
    logArc = graphBoxStart();
      graphArc(i, row+0.5, 0.7, 0, 360); 
      if (Pz.logFlag) graphFillArc(i, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(logArc, BLACK, TRANSPARENT);
    graphText("Log",i+1,row);
    i+=6.0;
    stdArc = graphBoxStart();
      graphArc(i, row+0.5, 0.7, 0, 360); 
      if (Pz.stdFlag) graphFillArc(i, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(stdArc, BLACK, TRANSPARENT);
    graphText("Stdout",i+1,row);
    graphButton("Help",Zhelp0,41,row);

    row += 2.0;
    graphLine(0.0,row,width,row);
    row += 1.0;

/** Draw building stuff **/
    i = 2.0;
    graphText("CB: Best contig of ",i,row);
    i += 19;
    bestBox = graphTextEntry(bestText, 4, i, row,hitCR);
    graphButton("Help",Zhelp2,41,row);

    row += 2.0;
    graphButton("Build Contigs (Runs Kill first)",Zbuild_contigs,col1,row);

    row += 2.0;
    graphButton("Kill",Zkill_all,col1,row);

    graphText("Contig size <= ",col1+7,row);
    ctgBox = graphTextEntry(ctgText, 5, col1+22.0, row,hitCR);
    
    seqArc = graphBoxStart();
      graphArc(col1+29, row+0.5, 0.7, 0, 360); 
      if (Zkill_seq) graphFillArc(col1+29, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(seqArc, BLACK, TRANSPARENT);
    graphText("Kill Seq Ctgs",col1+30,row);

    row += 2.5;
    graphButton("Incremental Build Contigs",Zincremental,col1,row);
    
    noCBArc = graphBoxStart();
      graphArc(col1+29, row+0.5, 0.7, 0, 360); 
      if (ZnoCB) graphFillArc(col1+29, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(noCBArc, BLACK, TRANSPARENT);
    graphText("NoCB on Existing",col1+30,row);

    row += 2.0;
    graphText("Last Build ",col1,row);
    new_year = Bd.date.year % 100; 
    if (new_year<10) sprintf(year,"0%d",new_year);
    else sprintf(year,"%d",new_year);

    sprintf(dateText,"%d/%d/%s %d:%d", Bd.date.day, Bd.date.month, 
          year, Bd.date.hour, Bd.date.minute); /* 15May07 CAS increased date entry */
    dateBox = graphTextEntry(dateText, 14, 13, row,hitCR);
    sprintf(tmp,"Cutoff %.0e%s",Bd.cutoff, CpMtype[Bd.useFlag]);
    graphText(tmp,29,row);

    //graphTextEntry(tolText, 0, 0, 0, NULL); /* make current box */
    row += 2.0;
    graphLine(0.0,row,width,row);
    row+=1.0;

/** reanalyze **/
    graphButton("DQer",DQ_ctgs,col1,row);
    row += .1;
    graphText("if >=",col1+6,row);
    qCutoffBox = graphTextEntry(qCutoffText,4,col1+11,row,hitCR);

    graphText("Qs  Step",col1+15,row);
    qCutoffBox = graphTextEntry(qDQStepText,2,col1+24,row,hitCR);

    qSplitArc = graphBoxStart();
      graphArc(col1+29, row+0.5, 0.7, 0, 360); 
      if (Pz.DQsplit) graphFillArc(col1+29, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(qSplitArc, BLACK, TRANSPARENT);
    graphText("No merge CBmaps",col1+30,row);

    row += 2.0;
    graphButton("ReBuild",reanalyze_all_ctgs,col1,row);
    i = col1+9;
    graphText("if",i,row);
    i += 4;
    qBuild1Arc = graphBoxStart();
      graphArc(i, row+0.5, 0.7, 0, 360); 
      if (Pz.rebuild) graphFillArc(i, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(qBuild1Arc, BLACK, TRANSPARENT);
    graphText("Q eq -",i+1,row);
    i+=9;
    qBuild2Arc = graphBoxStart();
      graphArc(i, row+0.5, 0.7, 0, 360); 
      if (!Pz.rebuild) graphFillArc(i, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(qBuild2Arc, BLACK, TRANSPARENT);
    graphText("Q eq ~",i+1,row);
    
    graphButton("Help",Zhelp3,41,row);
    row += 2.0;
    graphLine(0.0,row,width,row);
    row += 1.0;

/**** Begin Ends & KeySet block **/

    i=3.0;
    aaddArc = graphBoxStart();
      graphArc(i, row+0.5, 0.7, 0, 360); 
      if (Pz.autoaddFlag) graphFillArc(i, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(aaddArc, BLACK, TRANSPARENT);
    graphText("Auto Merge/Add",i+1,row);

    i+=17.0;
    graphText("FromEnd",i,row);
    i+=8.0;
    endBox = graphTextEntry(endText, 4, i, row,hitCR);

    graphButton("Help",Zhelp1,41,row);

    row += 2.0;
    i=2.0;
    graphButton("Ends-->Ends",matchends,i,row);
    i+=15.0;
    graphText("Match",i,row);
    i+=6.0;
    matchBox = graphTextEntry(matchText, 3, i, row,hitCR);

    if (fpc_tree_has_content(&seq_tree))
    {
        i += 10.0;
        seq_endsArc = graphBoxStart();
        graphArc(i, row + 0.5, 0.7, 0, 360); 
        if (ends_ends_seq_confirm) graphFillArc(i, row + 0.5, 0.4, 0, 360);
        graphBoxEnd();
        graphBoxDraw(seq_endsArc, BLACK, TRANSPARENT);
        graphText("Seq Confirm",i+1,row);
    }
    row += 2.0;
    i=2.0;

    graphButton("KeySet-->Fpc",keyset2fpc,i,row);
    i += 16.0;
    endsArc = graphBoxStart();
      graphArc(i, row+0.5, 0.7, 0, 360); 
      if (endsFlag) graphFillArc(i, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(endsArc, BLACK, TRANSPARENT);
    graphText("Ends Only",i+1,row);

    i += 12.0;
    ctg0Arc = graphBoxStart();
      graphArc(i, row+0.5, 0.7, 0, 360); 
      if (ctg0Flag) graphFillArc(i, row+0.5, 0.4, 0, 360);
      graphBoxEnd();
      graphBoxDraw(ctg0Arc, BLACK, TRANSPARENT);
    graphText("Include Ctg0",i+1,row);

    row += 2.0;
    graphLine(0.0,row,width,row);
    row += 1.0;

/** begin Clone comparison block **/
    i = 2.0;
    graphText("Clone:",i,row);
    i += 7.0;
    nameBox = graphTextEntry(ZnameText, CLONE_SZ-1, i, row,hitCR);
    i += CLONE_SZ;
    graphButton("-->Fpc",nameZfpc,i, row);
    graphButton("-->Key",nameZkeyset,i+8, row);
    graphButton("Help",Zhelp4,41,row);

/** end **/
    row += 2.0;
    graphLine(0.0,row,width,row);
    row += 1.0;
    graphButton("Close",quitClam2,2.0,row);
    graphText("All functions are F4 interruptable",9.0,row);

    cutBox = graphTextEntry(cutText,8,0,0,NULL);
    graphRedraw();
}

/*****************************************************************/
void scanClam2()
{
double tmp;
char buf[50];
char* pch;
  if (graphActivate(g92)) {
     sscanf(tolText,"%d",&Pz.tol);

     sscanf(cutText,"%lf",&tmp);
     if (tmp!=Pz.cutFlt) {
         if (tmp>1.0) {
            sprintf(buf, "Cutoff %.0e cannot be greater than 1", tmp);
            graphMessage(buf);
            NoPop=1; ClamCtgDisplay2(); NoPop=0;
            return;
         }
         else {
           Pz.cutFlt=tmp;
           ZautoCpM(1);
         }
     }
     sscanf(burText,"%f",&Pz.burFlt);
     sscanf(endText,"%d",&Pz.fromendInt);
     sscanf(matchText,"%d",&Pz.mergeMatches);
     sscanf(bestText,"%d",&Pz.bestInt);
     sscanf(dateText,"%d/%d/%d %d:%d",&Bd.date.day, &Bd.date.month, &Bd.date.year,
              &Bd.date.hour, &Bd.date.minute);
     if (strcmp(ctgText,"-1")==0 || strcasecmp(ctgText,"n")== 0 || 
         strcasecmp(ctgText,"max")== 0) Pz.killInt = -1;
     else sscanf(ctgText,"%d",&Pz.killInt);
     ClamShare(4);

     Pz.DQusePct = 0;
     strcpy(buf,qCutoffText);
     pch = strchr(buf,'%');
     if (0 != pch) {
        Pz.DQusePct = 1;
        *pch = 0;
     }
     sscanf(buf,"%d",&Pz.DQnumq);  
     sscanf(qDQStepText,"%d",&Pz.DQstep);  
     qDQFactor = exp(-Pz.DQstep*log(10));
  }
}
/*****************************************************************/
static void hitCR()
{
  scanClam2();
}

/*****************************************************************/
static void pickg9(int box,double x,double y)
{
  scanClam2(); /* WMN 7/27/04 moved here to catch all the cases where a textbox changed
                without hitting <cr> would revert to old value when user checked a radio button */

  if(box == tolBox) tolBox = graphTextEntry(tolText,8,0,0,NULL);
  else if(box == cutBox) cutBox = graphTextEntry(cutText,8,0,0,NULL);
  else if(box == burFltBox) burFltBox = graphTextEntry(burText,8,0,0,NULL);
  else if(box == endBox) endBox = graphTextEntry(endText,8,0,0,NULL);
  else if(box == matchBox) matchBox = graphTextEntry(matchText,8,0,0,NULL);
  else if(box == bestBox) bandBox = graphTextEntry(bestText,8,0,0,NULL);
  else if(box == ctgBox) ctgBox = graphTextEntry(ctgText,8,0,0,NULL);
  else if(box == nameBox) nameBox = graphTextEntry(ZnameText,8,0,0,NULL);
  else if (box == logArc) {
    Pz.logFlag = (!Pz.logFlag);
    if (Pz.logFlag) Zopenlog();
    else if (Zlogfp!=NULL) {
       fclose(Zlogfp);
       Zlogfp=NULL;
    }
    ClamCtgDisplay2();
  }
  else if (box == useCpMArc) {
    Cp.useFlag = (!Cp.useFlag);
    ZautoCpM();
    ClamCtgDisplay2();
  }
  else if (box == precomputeArc) {
    Pz.precompute = (!Pz.precompute);
    precompute_sulston();
    ClamCtgDisplay2();
  }
  else if (box == seqArc) {
    Zkill_seq = (!Zkill_seq);
    ClamCtgDisplay2();
  }
  else if (box == noCBArc) {
    ZnoCB = (!ZnoCB);
    ClamCtgDisplay2();
  }
  else if (box == aaddArc) {
    Pz.autoaddFlag = (!Pz.autoaddFlag);
    scanClam2();
    ClamCtgDisplay2();
  }
  else if (box == endsArc) {
    endsFlag = (!endsFlag);
    ClamCtgDisplay2();
  }
  else if (box == ctg0Arc) {
    ctg0Flag = (!ctg0Flag);
    ClamCtgDisplay2();
  }
  else if (box == stdArc) {
    Pz.stdFlag = (!Pz.stdFlag);
    ClamCtgDisplay2();
  }
  else if (box == qSplitArc) {
    Pz.DQsplit = (!Pz.DQsplit);
    ClamCtgDisplay2();
  }
  else if (box == qBuild1Arc) {
    Pz.rebuild = 1;
    ClamCtgDisplay2();
  }
  else if (box == qBuild2Arc) {
    Pz.rebuild = 0;
    ClamCtgDisplay2();
  }
  else if (box == seq_endsArc) {
    ends_ends_seq_confirm = (!ends_ends_seq_confirm);
    ClamCtgDisplay2();
  }

  NoPop=1; EvalCtgDisplay(); CBCtgDisplay(); NoPop=0;

  graphRedraw();
}
/*******************************************************************
                     DEF: nameZfpc
******************************************************************/
static void nameZfpc()
{
int i, cnt;
int index;
char mk[10];

  scanClam2();
  sprintf(ZBuf, "\n>> %s ctg%d %db --> Fpc  (Tol %d Cutoff %.0e%s)\n", 
      ZnameText, C1z.ctg, C1z.nbands, Pz.tol, Pz.cutFlt, CpMtype[Cp.useFlag]); Output;
  clearMsg();

  removespaces(ZnameText);
  if(!fppFindClone(ZnameText,&index)) {   
      sprintf(scoreText,"ERROR could not find clone %s",ZnameText); Show;
      return;
  }

  if (!loadCz(&C1z, index)) {
      sprintf(ZBuf, "*** No %s\n",ZnameText); Output;
      return;
  }
  for (cnt=i=0; i< arrayMax(acedata); i++) 
  {
       if (!loadCz(&C2z, i)) continue;
       if (strcmp(C2z.clone, C1z.clone)==0) continue;
       if (C2z.clone[0]=='!') continue;

        Zsulston(&C1z,&C2z,&Sz);
        if (ZboolCpM()) { /* CLONE_SZ*/
             if (Sz.mark > 0) sprintf(mk, "%2d",Sz.mark);
             else strcpy(mk,"  ");
             sprintf(ZBuf, "Ctg%-4d %15s %2db   %3d %.0e %s %15s   %s\n",
                C2z.ctg, C2z.clone, C2z.nbands, Sz.match, Sz.prob, mk,
                C2z.parent, C2z.btype); Output;
             cnt++;
        }
  }
  sprintf(scoreText,"--> %s hits %d ", ZnameText, cnt); Show;
}
/*******************************************************************
                     DEF: nameZkeyset
******************************************************************/
static void nameZkeyset()
{
int index;
char mk[10];
struct list *p;
CLONE *clone;


   removespaces(ZnameText);
   if(!fppFindClone(ZnameText,&index)) {   
      sprintf(scoreText,"ERROR could not find clone %s",ZnameText); Show;
      return;
   }
   if (!loadCz(&C1z, index)) {
      sprintf(scoreText,"Error with %s",ZnameText); Show;
      return;
   }
   if ((classctg!= CLONECLASS || !graphExists(g2))) {
           /* use clone text window is exists */
      if (graphExists(g7) && clonedisplayed>= 0) {
         clone = arrp(acedata, clonedisplayed, CLONE);
         if (!loadCz(&C2z, clonedisplayed)) return;
         Zsulston(&C1z,&C2z,&Sz);
         if (Sz.mark > 0) sprintf(mk, "%2d",Sz.mark);
         else strcpy(mk,"  ");
         sprintf(scoreText, "%15s %15s %3db %3db  %3d %.0e %s\n",
              C1z.clone, C2z.clone, C1z.nbands, C2z.nbands,
              Sz.match, Sz.prob, mk); Show;
         sprintf(ZBuf,"%s", scoreText); Output;
         return;
      }
      fprintf(stderr,"No clone keyset\n");
      return;
   }
   scanClam2();
   sprintf(ZBuf, "\n>> %s ctg%d %db --> KeySet  (Tol %d)\n", 
      ZnameText, C1z.ctg, C1z.nbands, Pz.tol); Output;
   for (p=listroot; p!=NULL; p = p->next)
   {
        if (graphInterruptCalled()) {
           printf("User Interrupt - pre-mature termination of Clone --> KeySet\n");
           break;
        } 
        clone = arrp(acedata, p->index, CLONE);

        if (!loadCz(&C2z, p->index)) continue;
        if (strcmp(C2z.clone, C1z.clone)==0) continue;

        Zsulston(&C1z,&C2z,&Sz);
        if (Sz.mark > 0) sprintf(mk, "%2d",Sz.mark);
        else strcpy(mk,"  ");
        sprintf(ZBuf, "Ctg%-4d %15s %2db   %3d %.0e %s %15s   %s\n",
              C2z.ctg, C2z.clone, C2z.nbands, Sz.match, Sz.prob, mk,
              C2z.parent, C2z.btype); Output;
   }
}
/**********************************************************************
                    DEF: kill_all
**********************************************************************/
static int kill_all()
{
int  c, save, cnt, i;
int rc=1, max = 0;
CLONE *clp;
MARKER *mkp;
struct markerctgpos *pos, *next;
struct tms tmsstart,tmssend;
clock_t start=0,end=0;
void initContig();

   if(ctg_window!=NULL) gtk_widget_destroy(ctg_window);
   save = max_contig;
   scanClam2();
   for (cnt=0, i=1; i<= max_contig && cnt == 0; i++) 
        if (contigs[i].seq>0)  cnt++;
   start=times(&tmsstart);
   
PRTMESS=0;
   if (Pz.killInt == -1 && (Zkill_seq==1 || cnt==0)) { /* kill everything quickly */
       sprintf(scoreText, "Kill all contigs.");
       sprintf(ZBuf, "Start Killing all contigs....\n"); Outlog;
       for (i=0; i<arrayMax(acedata); i++) {     /* clones */
            clp = arrp(acedata, i, CLONE);
            if (clp->ctg == 0) continue;
            clp->match[0]=' ';
            clp->parent = -1;
            clp->mattype = 0;
            clp->ctg= clp->x = clp->y = 0;
            clp->next = -1;
            if(contigs[0].count > 0){
               arrp(acedata,contigs[0].last,CLONE)->next = i;
            }
            else{
               contigs[0].start = i;
            }
            contigs[0].last = i;
            contigs[0].count++;
            AddToCtgSeq(clp, 0);
       }
       for (i=0; i<arrayMax(markerdata); i++) {  /* markers */
            mkp = arrp(markerdata, i, MARKER);
            for(pos = mkp->pos; pos != NULL; ) {
                next = pos->next;
                messfree(pos);
                pos = next;
            }
            mkp->pos = NULL;
       }
       for (i=1; i<= max_contig; i++) {         /* contigs */
           initContig(i);
       } 
       end=times(&tmssend);
       pr_end_timer("Kill:", end-start,&tmsstart,&tmssend);
       ZBuf[0]='\0'; 
       max_contig=0;
       refreshlist();
       PRTMESS=1;
       return 1;
   }

   if (Pz.killInt== -1) {
         for (i=1; i<= max_contig; i++)
            max = MaX(max, contigs[i].count);
   }
   else max = Pz.killInt;
   sprintf(ZBuf,"Start killing contigs with < %d clones.\n",max); Outlog;
   for (cnt=0, i=1; i<= max_contig; i++)
   {
      if (!Zbatch_flag && graphInterruptCalled()) {
          printf("User Interrupt - pre-mature termination of Kill\n");
          rc=0;
          break;
      } 
      if (contigs[i].count == 0) continue;
      if (NoBuild(i)) continue;
      if (contigs[i].seq > 0 && Zkill_seq==0) continue;
      if (contigs[i].count > max) continue;
      for (c=contigs[i].start;  c != -1; c = arrp(acedata, c, CLONE)->next) {
         if (arrp(acedata, c, CLONE)->match[0]!=' ') unbury(c);
         arrp(acedata, c, CLONE)->selected = TRUE;
      }
      move_selected(i, 0, 0);
      contigs[i].count=0;
      cnt++;
      if ((cnt % 1000)==0 && !Zbatch_flag) fprintf(stderr," killed %d..\n",cnt);
   }
   for (c=contigs[0].start;  c != -1; c = arrp(acedata, c, CLONE)->next) 
       arrp(acedata, c, CLONE)->selected = FALSE;
PRTMESS=1;
   for (c=0,i=1, max_contig=0; i <= save; i++)
       if  (contigs[i].count > 0) {max_contig = i; c++; }
   sprintf(ZBuf,"Kill %d contigs.  Remaining Contigs %d. Max contig %d.\n", 
               cnt, c, max_contig); Outlog;
   sprintf(scoreText, "Kill %d contigs.", cnt);
   end=times(&tmssend);
   pr_end_timer("Kill:", end-start,&tmsstart,&tmssend);
   refreshlist();
   updateproj();
return rc;
}
/************************************************************************
                       DEF: Zkill_all
************************************************************************/
void Zkill_all()
{
kill_all();
Show; 
}
/************************************************************************
                       DEF: Zincremental
************************************************************************/
void Zincremental()
{
   scanClam2();
   precompute_sulston();
   Zincremental_build_zap();
}
/************************************************************************
                       DEF: Zbuild_contigs
************************************************************************/
void Zbuild_contigs()
{
printf("\n>>> Kill/Build/OKall:\n");
  if (kill_all()) 
  {
     PRTMESS=0;
     scanClam2();
     precompute_sulston();
     Zbuild_contigs_zap();
     PRTMESS=1;
  }
}
/************************************************************************
                       DEF: Zbuild_batch
************************************************************************/
void Zbuild_batch(int k)
{
Zbatch_flag=1;
Pz.killInt=k;
Zbuild_contigs();
save_fpc_safe();
}

/*************************************************************************
                      DEF: reanalyze_ctgs
                      Friedrich Engler
                      efriedr 12/6/01
*************************************************************************/
int get_q_threshold(int i) {
   int thresh = Pz.DQnumq;
   float fthresh;


   if (1 == Pz.DQusePct) {
      fthresh = ( ((float)contigs[i].count)*((float)Pz.DQnumq) )/100.0;  
      thresh = (int)(fthresh + .99);
   }  
   if (thresh == 0 || thresh == 1)
   {
      thresh = 1;
   }

   return thresh;
}


static void DQ_ctgs(){
   int cnt, i,j,k;
   double tempCutFlt;
   double tempCpM[MAX_CpM], tempCpM2[MAX_CpM];  
   int tempctg;
   int qBefore=0, nBefore=0;
   int qAfter=0, nAfter=0;
   int qIteration=0, cntDQed=0;
   int maxBefore;
   int last, ctgMaxQs = -1;
   int maxQs=0;
   int ZibcCpM();
   void Zcalc_zap(), CBlayout(), displayProj();
   clock_t start=0,end=0;
   struct tms tmsstart,tmssend;

   if(ctg_window!=NULL) gtk_widget_destroy(ctg_window);
   precompute_sulston();

   scanClam2();
   tempctg=currentctg;
   if(!ZibcCpM()){ fprintf(stdout,"Contigs unchanged.\n"); return;}
   tempCutFlt=Pz.cutFlt;
   for(k=1;k<MAX_CpM;k++)    tempCpM[k]=CpM[k].cut;

   if (Pz.DQsplit==1) printf("Start DQer: Move extra CBmaps to new contigs\n");
   else printf("Start DQer: Try to merge CBmaps\n");

   maxBefore=max_contig;
   Znum_merge=Znum_ctg0=0;

   for(i=1;i<=max_contig;i++){
      if(contigs[i].ctgQs >= get_q_threshold(i)){
         qBefore++;
      }
      if(contigs[i].approxQs){
         nBefore++;
      }
      contigs[i].projmsg[0] = '\0';
   }

   start=times(&tmsstart);
                                         
   for(j=0;j<3;j++){
      for(qIteration=0,i=1;i<=max_contig;i++)
          if(contigs[i].ctgQs >= get_q_threshold(i))
             qIteration++;
      cnt=0;
      
      Pz.cutFlt=Pz.cutFlt*qDQFactor;    /*calc more stringent cutoffs...*/

      for(k=1;k<MAX_CpM;k++)     
         CpM[k].cut=CpM[k].cut*qDQFactor;

      sprintf(ZBuf,"\n>> DQing %d contigs at cutoff %.0e\n",qIteration,
                          Pz.cutFlt); Outlog;
      if (qIteration==0) break;

      last = max_contig;
      for(cnt=0, i=1;i<=last;i++){
         if(contigs[i].ctg == 0) continue;
         if(contigs[i].ctgQs < get_q_threshold(i)) continue;
         if(contigs[i].ctgstat == DEAD || contigs[i].ctgstat == NoCB ||
            contigs[i].ctgstat == AVOID) continue;

         sprintf(ZBuf,"\nStarting ctg%d Qs %d  Clones %d  (%d of %d)\n", i, 
            contigs[i].ctgQs, contigs[i].count, cnt+1,qIteration); Outlog;
         qstuff=1;
         currentctg=contigs[i].ctg;
         find_Clone(i);  /* put the contig into the contig structure */
         Zall_unbury();
         LastCB = DQ;
         Zcalc_zap();
            /* CBlayout function needs original CpM cutoffs, so copy in; */
         for(k=1;k<MAX_CpM;k++) tempCpM2[k]=CpM[k].cut;
         for(k=1;k<MAX_CpM;k++) CpM[k].cut=tempCpM[k];
         CBlayout();
         for(k=1;k<MAX_CpM;k++) CpM[k].cut=tempCpM2[k];
         if(graphInterruptCalled()) break;
         cntDQed++;
         cnt++;
      }
   }
   end=times(&tmssend);
   Zfree_cb_data_structures();

   for(i=1;i<=max_contig;i++){
      if(contigs[i].ctgQs>maxQs){
         maxQs=contigs[i].ctgQs;
         ctgMaxQs=contigs[i].ctg;
      }
      if(contigs[i].ctgQs >= get_q_threshold(i))
         qAfter++;
      if(contigs[i].approxQs)
         nAfter++;
   }

   sprintf(ZBuf,"\nDQ'ed %d contigs complete.\n", cntDQed); Outlog;
   sprintf(ZBuf,"Contigs Qs >%3s: Before %d After %d \n",
                     qCutoffText,qBefore,qAfter); Outlog;
   sprintf(ZBuf,"Contigs Qs eq ~: Before %d After %d \n",
                     nBefore,nAfter); Outlog;
   sprintf(ZBuf,"New contigs %d  Clones moved to ctg0 %d\n",
                max_contig-maxBefore, Znum_ctg0); Outlog;
   if (ctgMaxQs != -1)
      sprintf(ZBuf,"Ctg%d has the most Qs (%d).\n",ctgMaxQs,maxQs);
   else sprintf(ZBuf,"\n");
   Outlog;
   pr_end_timer("DQer:", end-start,&tmsstart,&tmssend);
   sprintf(ZBuf,"DQ'ed %d contigs",cntDQed); showClam2();

   Pz.cutFlt=tempCutFlt;
   for(k=1;k<MAX_CpM;k++) CpM[k].cut=tempCpM[k];
   currentctg=tempctg;
   ZburyFlag=1;
   qstuff=0;
   fix_cb_offsets();
   Zproj_results(0); /* project window */
}

/*************************************************************************
                      DEF: reanalyze_all_ctgs
Reanalyzes all ctgs with unknown Q value.  Does not increase stringency.
Does not move unconnected to new contigs.
*************************************************************************/
static void reanalyze_all_ctgs(){
   int i;
   double tempCutFlt;
   int tempctg;
   int qBefore=0, qAfter=0, cnt=0;
   int nBefore=0, nAfter=0;
   int aBefore=0, aAfter=0;
   int ctgMaxQs = -1;
   int maxQs=0;
   int ZibcCpM();
   void Zcalc_zap(), CBlayout(), displayProj();
   clock_t start=0,end=0;
   struct tms tmsstart,tmssend;

   if(ctg_window!=NULL) gtk_widget_destroy(ctg_window);
   precompute_sulston();

   scanClam2();
   tempctg=currentctg;
   if(!ZibcCpM()){ fprintf(stdout,"Contigs unchanged.\n"); return;}
   tempCutFlt=Pz.cutFlt;

   for(i=1;i<=max_contig;i++){
      if(contigs[i].ctgQs >= get_q_threshold(i)) qBefore++;
      if(contigs[i].approxQs) aBefore++;
      if(contigs[i].ctgQs < 0) nBefore++;
      contigs[i].projmsg[0] = '\0';
   }
   start=times(&tmsstart);

   if (Pz.rebuild==1)
      sprintf(ZBuf,"\n>> Rebuild %d contigs (Qs eq -) at cutoff %.0e\n",nBefore, Pz.cutFlt);
   else
      sprintf(ZBuf,"\n>> Rebuild %d contigs (Qs eq ~) at cutoff %.0e\n",aBefore, Pz.cutFlt);
   Outlog;
   for(i=1;i<=max_contig;i++){
         if(contigs[i].ctg == 0) continue;
         if(contigs[i].ctgstat == DEAD || 
            contigs[i].ctgstat == AVOID ||
            contigs[i].ctgstat == NoCB) continue;
         if(Pz.rebuild==0 &&  contigs[i].approxQs == 1) {
            cnt++;
            sprintf(ZBuf,"\nStarting ctg%-6d clones %d  Qs: ~%d  (%d of %d)\n",
                   contigs[i].ctg, contigs[i].count, contigs[i].ctgQs, cnt, aBefore);
            Outlog;
         }
         else if (Pz.rebuild==1 && contigs[i].ctgQs == -1) {
            cnt++;
            sprintf(ZBuf,"\nStarting ctg%-6d clones %d  Qs: -  (%d of %d)\n",
                        contigs[i].ctg, contigs[i].count, cnt, nBefore);
            Outlog;
         }
         else continue;

         qstuff=1;
         qstuff_nosplit=1;
         currentctg=contigs[i].ctg;
         setmarkerposctg();
         find_Clone(i);
         Zall_unbury();
         LastCB = NoQ;
         Zcalc_zap();
         CBlayout();
         if(graphInterruptCalled()) break;
   }
   end=times(&tmssend);
   Zfree_cb_data_structures();

   for(i=1;i<=max_contig;i++){
      if(contigs[i].ctgQs>maxQs){
         maxQs=contigs[i].ctgQs;
         ctgMaxQs=contigs[i].ctg;
      }
      if(contigs[i].approxQs) aAfter++;
      if(contigs[i].ctgQs >= get_q_threshold(i)) qAfter++;
      if(contigs[i].ctgQs < 0) nAfter++;
   }
   sprintf(ZBuf,"\nComplete reanalyzing contigs with unknown Qs.\n"); 
   sprintf(ZBuf,"Contigs Qs >%3s: Before %d After %d \n",
                     qCutoffText,qBefore,qAfter); Outlog;
   sprintf(ZBuf,"Contigs Qs eq ~: Before %d After %d \n",
                     aBefore,aAfter); Outlog;
   sprintf(ZBuf,"Contigs Qs eq -: Before %d After %d \n",
                     nBefore,nAfter); Outlog;
   pr_end_timer("Reanalyze:", end-start,&tmsstart,&tmssend);
   sprintf(ZBuf,"Reanalyzed %d contigs",nBefore); showClam2();

   Pz.cutFlt=tempCutFlt;
   currentctg=tempctg;
   setmarkerposctg();
   qstuff=0;
   qstuff_nosplit=0;
   fix_cb_offsets();
   Zproj_results(0); /* project window */
}

/********************************************************************
                        addtolist
********************************************************************/
static struct keylist
{
  int left, right, ctg;
  double prob;
  char msg[80];
} *Klist=NULL;
static int Knum=0, Kmax=0, *Kadd;

static void addtolist()
{
char mk[10];
   if (Knum >=Kmax) {
       Kmax += 20;
       if (Klist==NULL) 
          Klist = (struct keylist *) malloc(sizeof(struct keylist) * Kmax);
       else 
          Klist = (struct keylist *) realloc(Klist, sizeof(struct keylist) * Kmax);
       if (Klist==NULL) {
          fprintf(stderr,"Ran out of memory for clone %s at %d\n",
              C1z.clone, Kmax);
          Kmax=0;
          return;
       }
   }
   Klist[Knum].ctg = C2z.ctg;
   Klist[Knum].left = C2z.left;
   Klist[Knum].right = C2z.right;
   Klist[Knum].prob = Sz.prob;
   if (Sz.mark>0) sprintf(mk, "%2d",Sz.mark);
   else strcpy(mk, "  ");
   sprintf(Klist[Knum].msg, 
    "   Ctg%-4d %12s  %2db  %3d %.0e %s %12s %s\n",
        C2z.ctg, C2z.clone, C2z.nbands, Sz.match, Sz.prob, mk,
        C2z.parent, C2z.btype);
   Knum++;
}
static void freelist()
{
   if (Klist!=NULL) free(Klist);
   Klist=NULL;
   Knum=Kmax=0;
}
static void orderPrintList(int x) 
{
int i, j, ctg, c1, cnt, cnt1;
struct keylist tmp;
CLONE *clp;
int left, right, z;
float p1, p2;

  if (Knum==0) return; 
               /* CLONE_SZ */
  sprintf(ZBuf, "%-3d Clone %-15s Ctg%-3d %2db\n", 
        x, C1z.clone, C1z.ctg, C1z.nbands); 
  Output;

  for (i=0; i<Knum-1; i++)
       for (j=i+1; j<Knum; j++) {
           if (Klist[i].ctg > Klist[j].ctg) {
               tmp = Klist[i];
               Klist[i] = Klist[j];
               Klist[j] = tmp;
           }
       }
   if (!Pz.autoaddFlag || C1z.ctg!=0) goto RESULTS;
   
   ctg = c1 = Klist[0].ctg; 
   cnt1 = 1; p1 = Klist[0].prob; 
   cnt = 0;  p2=0.0; 
   for (i=1; i<=Knum; i++) { /* find best contig */
        if (i!=Knum && c1 == Klist[i].ctg) {
            cnt1++; 
            if (p1 > Klist[i].prob) p1 = Klist[i].prob;
        }
        else {
            if (cnt1 >cnt || (cnt1==cnt && p1 < p2)) {
                ctg = c1;
                cnt = cnt1;
                p2 = p1;
            }
            cnt1=1;
            p1= Klist[i].prob;
            c1 = Klist[i].ctg;
        }
   }
   if (ctg==0) goto RESULTS;

   left = INT_MAX; right = INT_MIN;
   for (i=0; i<Knum; i++)
        if (ctg == Klist[i].ctg)  {
            left = MiN(left, Klist[i].left);
            right = MaX(right, Klist[i].right);
        }
   clp = arrp(acedata, C1z.cin, CLONE);
   clp->selected = TRUE;
   if (left - Pz.fromendInt <= contigs[ctg].left) {
       clp->x = left;
       clp->y = left + C1z.nbands;
   }
   else if (right + Pz.fromendInt >= contigs[ctg].right) {
       clp->x = right - C1z.nbands;
       clp->y = right;
   } 
   else {
       z = (left + right)/2;
       clp->x = z - (C1z.nbands >> 1);
       clp->y = z + (C1z.nbands >> 1);
   }
   PRTMESS=0;
   move_selected(0, ctg, 0);
   PRTMESS=1;
   clp->selected = FALSE;
   sprintf(ZBuf, "Add to Ctg%d (%d, %d)\n", ctg, clp->x, clp->y); 
   Output;
   Kadd[ctg]++;
  
RESULTS: ;
  
  for (i=0; i<Knum; i++) {
     sprintf(ZBuf, "%s", Klist[i].msg); 
     Output;
  }
  Knum=0;
}
/*******************************************************************
                     DEF: keyset2fpc
called from batch.c
******************************************************************/
void keyset2fpc()
{
struct list *p;
CLONE *clp;
int c, i, k,m, cnt, cnt0, cnt1, cnt2;
int *ctg;
int x=0;
char stmp[300];

   precompute_sulston();

   if ((classctg!= CLONECLASS || !graphExists(g2)) && !Zbatch_flag) {
      strcpy(scoreText,"No keyset of clones"); Show;
      fprintf(stderr, "No keyset of clones\n"); 
      return;
   }
   scanClam2();
   clearMsg();
   ctg = (int *) malloc(sizeof(int) * (max_contig+2));
   NOMEM2(ctg, "ctg");
   Kadd = (int *) malloc(sizeof(int) * (max_contig+2));
   NOMEM2(Kadd, "Kadd");
   for (i=0; i <= max_contig; i++) {
      contigs[i].projmsg[0] = '\0';
      ctg[i]=0;
      Kadd[i]=0;
   }
   if (Pz.autoaddFlag) { 
     for(i=1;i<=max_contig;i++){
        if(contigs[i].count==0) continue;
        for(c=contigs[i].start; c!=-1;c=clp->next){
           clp = arrp(acedata, c, CLONE);
           clp->oldctg=clp->ctg;
           clp->ibc=0;
        }
     }
   }
   sprintf(ZBuf, "\n>> KeySet --> Fpc  (Tol %d Cutoff %.0e%s) ", 
           Pz.tol, Pz.cutFlt, CpMtype[Cp.useFlag]); 
   if (endsFlag) {
      sprintf(stmp,"FromEnd %d",Pz.fromendInt);
      strcat(ZBuf, stmp);
   }
   else if (ctg0Flag) {
      strcat(ZBuf, "Include ctg0");
   }
   strcat(ZBuf, "\n");
   Output;

   m=k=cnt= cnt0=0;
   for (p=listroot; p!=NULL; p = p->next)
   {
        x++;
        if (graphInterruptCalled()) {
           printf("User Interrupt - pre-mature termination of KeySet->Ctg\n");
           break;
        } 
        clp = arrp(acedata, p->index, CLONE);

        if (!loadCz(&C1z, p->index)) {
           sprintf(ZBuf, ">> Clone %s ctg%d - ignored\n", clp->clone, clp->ctg); 
           Output;
           continue;
        }
        m++;
        for (k=i=0; i< arrayMax(acedata); i++) 
        {
           if (!loadCz(&C2z, i)) continue;
                      /* 11May07 WMN prevent singleton comparison */
           if (C2z.ctg == 0 && !ctg0Flag) continue; 
           if (strcmp(C2z.clone, C1z.clone)==0) continue;
           if (C2z.clone[0]=='!') continue;

           if (endsFlag) { /* 11May07 CAS */
               c = C2z.ctg;
               clp = arrp(acedata, i, CLONE);
               if (! (clp->x-Pz.fromendInt <= contigs[c].left ||
                      clp->y+Pz.fromendInt >= contigs[c].right))
                            continue;
           } 

           Zsulston(&C1z,&C2z,&Sz);
           if (ZboolCpM()) {
              addtolist();
              k++;
              cnt0++;
              ctg[C2z.ctg]++;
           }
         }
         if (k>0) cnt++;
         orderPrintList(x);
  }
  freelist();
  cnt1 = cnt2 = 0;
  for (i=1; i<= max_contig; i++) 
     if (ctg[i] > 0) {
        if (Kadd[i]> 0)  {
           sprintf(stmp, "Add %d.", Kadd[i]);
           AutoCtgMsg(i, stmp);
           sprintf(contigs[i].projmsg,"Hits %d Add %d",ctg[i], Kadd[i]);
        }
        else
           sprintf(contigs[i].projmsg,"Hits %d",ctg[i]);
        cnt1+= ctg[i];
        cnt2++;
     }
     sprintf(scoreText,"--> KeySet hits %d in %d ctgs", cnt1, cnt2); Show;
     sprintf(ZBuf, "KeySet %d clones %d hits %d\n", m,cnt, cnt0); Output;
     free(ctg); free(Kadd);
     if (Zlogfp) fflush(Zlogfp);
     if(!Zbatch_flag)  
     Zproj_results(0);
}
